home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-10 | 10.2 KB | 377 lines | [TEXT/PJMM] |
-
- (* KeyConfig *)
-
- (* }
- {By Ingemar Ragnemalm 1995}
- {This program shows a modal dialog box, in which you can select eight keys,}
- {supposedly fr keyboard control for a game, plus a three-button set of radio}
- {buttons and a checkbox. It also shows the key codes found for each key.}
- {}
- {You should study this program when making your own key configuration dialogs.}
- {The most important message is that you should get the key codes through events,}
- {not assume that everybody has the same key configuration as you have.}
- {*)
-
- program KeyConfig;
-
- uses
- {$ifc UNDEFINED THINK_PASCAL}
- Types, QuickDraw, Events, Windows, Dialogs, Fonts, DiskInit, TextEdit, Traps,{}
- Memory, SegLoad, Scrap, ToolUtils, OSUtils, Menus, Resources, StandardFile, {}
- GestaltEqu, Files, Errors, Packages, OSEvents,
- {$endc}
- Preferences;
-
-
- (* Prefs record *)
-
- type
- PrefsRec = record
- keyCodes: array[0..7] of char; (* Key codes *)
- keyChars: array[0..7] of char; (* ASCII values *)
- myRadio: Integer;
- myCheckBox: Boolean;
- end;
-
- PrefsPtr = ^PrefsRec;
- PrefsHnd = ^PrefsPtr;
-
-
- var
- gPrefs: PrefsHnd;
-
- gTempKeyCodes: array[0..7] of char; (* Key codes, temporary stoareg while the dialog is open *)
-
- (* The following constants must match the DLOG/DITL resource! *)
- const
- kHighDlogRes = 128;
- kOKButton = 1;
- kCancelButton = 2;
- kFirstKey = 3;
- kLastKey = 10;
- kFirstRadio = 11;
- kLastRadio = 13;
- kCheckBox = 14;
- kFirstCode = 15;
- kLastCode = 22;
-
-
- (* StdFilter *)
-
- (* StdFilter is a dialog filter function that is useful for most}
- {modal dialogs, as long as they have an OK and a Cancel button.}
- {It maps return and enter to OK, and command-period and ESC to Cancel.}
- {It also draws a frame around the OK button. *)
-
- function StdFilter (theDialog: DialogPtr; var theEvent: EventRecord; var itemHit: Integer): Boolean;
-
- var
- theChar: char;
- kind: Integer;
- item: Handle;
- box: Rect;
-
- begin
- case theEvent.what of
- keyDown:
- begin
- theChar := char(BAnd(theEvent.message, charCodeMask));
- if ((BAnd(theEvent.modifiers, cmdKey)) <> 0) and (theChar = '.') or (theChar = char(27)) then (*cmd-. or ESC*)
- begin
- itemHit := kCancelButton;
- (*Highlight the cancel button*)
- GetDItem(theDialog, kCancelButton, kind, item, box);
- HiliteControl(ControlHandle(item), 1);
-
- StdFilter := true;
- exit(StdFilter);
- end;
- if (theChar = char(13)) or (theChar = char(3)) then
-
- begin
- itemHit := kOKButton;
- (*Highlight the OK button*)
- GetDItem(theDialog, 1, kind, item, box);
- HiliteControl(ControlHandle(item), kOKButton);
-
- StdFilter := true;
- exit(StdFilter);
- end;
- end; (*keyDown*)
- updateEvt:
- begin
- BeginUpdate(theDialog);
- SetPort(theDialog);
-
- DrawDialog(theDialog);
-
- (*Frame default button - item 1*)
- GetDItem(theDialog, kOKButton, kind, item, box);
- InsetRect(box, -4, -4);
- PenSize(3, 3);
- FrameRoundRect(box, 15, 15);
-
- EndUpdate(theDialog);
- end; (*update event*)
- end; (*case*)
- StdFilter := false;
- end; (*StdFilter*)
-
-
-
- function KeysFilter (theDialog: DialogPtr; var theEvent: EventRecord; var itemHit: Integer): Boolean;
-
- var
- item: Integer;
- theKeyNumber: Integer;
-
- itemHandle: Handle;
- itemType: Integer;
- itemRect: Rect;
- str: Str255;
- begin
- if BAnd(theEvent.modifiers, cmdKey) <> 0 then (*Command key held down*)
- KeysFilter := StdFilter(theDialog, theEvent, itemHit)
- else if theEvent.what <> keyDown then (*Not a keydown*)
- KeysFilter := StdFilter(theDialog, theEvent, itemHit)
- else if BAnd(theEvent.message, charCodeMask) = 3 then (*Enter*)
- KeysFilter := StdFilter(theDialog, theEvent, itemHit)
- else if BAnd(theEvent.message, charCodeMask) = 13 then (*Return*)
- KeysFilter := StdFilter(theDialog, theEvent, itemHit)
- else if BAnd(theEvent.message, charCodeMask) = 27 then (*Escape*)
- KeysFilter := StdFilter(theDialog, theEvent, itemHit)
- else if BAnd(theEvent.message, charCodeMask) = 9 then (*TAB*)
- KeysFilter := StdFilter(theDialog, theEvent, itemHit)
- else
- (* Get the key code *)
- begin
- theKeyNumber := BSR(BAnd(theEvent.message, keyCodeMask), 8);
-
- if IsDialogEvent(theEvent) then
- if DialogSelect(theEvent, theDialog, item) then
- begin
- itemHit := item;
-
- (* If it is one of the key boxes, put the key code in the temprary array *)
- if (itemHit >= kFirstKey) and (itemHit <= kLastKey) then
- begin
- gTempKeyCodes[itemHit - kFirstKey] := char(theKeyNumber);
-
- (* Just for the demo, I also display the key codes. A real game would never do that. *)
- NumToString(theKeyNumber, str);
- GetDItem(theDialog, itemHit - kFirstKey + kFirstCode, itemType, itemHandle, itemRect);
- SetIText(itemHandle, str);
-
- KeysFilter := true;
- exit(KeysFilter);
- end;
- end;
- end;
- end; (* KeysFilter*)
-
-
- (* AskKeys *)
- (* This is the procedure that handles the dialog. *)
-
- function AskKeys (prefs: PrefsHnd): Boolean;
-
- var
- theDialog: DialogPtr;
- oldPort: GrafPtr;
- itemHit: Integer;
- itemHandle: Handle;
- itemType: Integer;
- itemRect: Rect;
- str: Str255;
- itemNo: Integer;
- theFlag: Boolean;
- returnValue: Boolean;
-
- begin
- returnValue := false;
-
- GetPort(oldPort);
- theDialog := GetNewDialog(kHighDlogRes, nil, WindowPtr(-1));
- ShowWindow(theDialog);
- SelectWindow(theDialog);
- SetPort(theDialog);
-
- (* Set all dialog items to their initial values *)
-
- (* First set all the editable text boxes… *)
- for itemNo := kFirstKey to kLastKey do
- begin
- GetDItem(theDialog, itemNo, itemType, itemHandle, itemRect);
- str[0] := char(1); (* Length 1 *)
- str[1] := prefs^^.keyChars[itemNo - kFirstKey]; (* Put the char in the string *)
- SetIText(itemHandle, str);
- end;
-
- (* …then the radio buttons… *)
- for itemNo := kFirstRadio to kLastRadio do
- begin
- GetDItem(theDialog, itemNo, itemType, itemHandle, itemRect);
- SetCtlValue(ControlHandle(itemHandle), Integer(itemNo = prefs^^.myRadio));
- end;
-
- (* …and the checkbox… *)
- GetDItem(theDialog, kCheckBox, itemType, itemHandle, itemRect);
- SetCtlValue(ControlHandle(itemHandle), Integer(prefs^^.myCheckBox));
-
- (* Finally, copy all the key codes to a temporary storage. *)
- for itemNo := 0 to kLastKey - kFirstKey do
- begin
- gTempKeyCodes[itemNo] := prefs^^.keyCodes[itemNo];
-
- (* Just for the demo, I also display the key codes. A real game would never do that. *)
- NumToString(Longint(prefs^^.keyCodes[itemNo]), str);
- GetDItem(theDialog, itemNo + kFirstCode, itemType, itemHandle, itemRect);
- SetIText(itemHandle, str);
- end;
-
-
- (* One more thing: let the first key be selected *)
- SelIText(theDialog, kFirstKey, 0, 1);
-
- itemHit := -1;
- while ((itemHit <> 1) and (itemHit <> 2)) do (* 1=ok, 2=cancel *)
- begin
- ModalDialog(@KeysFilter, itemHit);
-
- (* Handle radio buttons and checkboxes here *)
- if (itemHit = kCheckBox) then
- begin
- GetDItem(theDialog, itemHit, itemType, itemHandle, itemRect);
- theFlag := Boolean(GetCtlValue(ControlHandle(itemHandle)));
- SetCtlValue(ControlHandle(itemHandle), Integer(not theFlag));
- end;
-
- if (itemHit >= kFirstRadio) and (itemHit <= kLastRadio) then
- for itemNo := kFirstRadio to kLastRadio do
- begin
- GetDItem(theDialog, itemNo, itemType, itemHandle, itemRect);
- SetCtlValue(ControlHandle(itemHandle), Integer(itemNo = itemHit));
- end;
-
- (* If it was a key, select it *)
- if (itemHit >= kFirstKey) and (itemHit <= kLastKey) then
- SelIText(theDialog, itemHit, 0, 32767);
-
- end; (*while*)
-
- (* If not cancelled, put the results in the prefs structure. *)
-
- if (itemHit = 1) then
-
- (* Get values from the dialog items *)
-
- (* First get all the editable text boxes… *)
- begin
- for itemNo := kFirstKey to kLastKey do
- begin
- GetDItem(theDialog, itemNo, itemType, itemHandle, itemRect);
- GetIText(itemHandle, str);
- if (str[0] <> char(0)) then (* If it's empty, leave it alone. *)
- prefs^^.keyChars[itemNo - kFirstKey] := str[1];
- end;
-
- (* …then the radio buttons… *)
- for itemNo := kFirstRadio to kLastRadio do
- begin
- GetDItem(theDialog, itemNo, itemType, itemHandle, itemRect);
- if Boolean(GetCtlValue(ControlHandle(itemHandle))) then
- prefs^^.myRadio := itemNo;
- end;
-
- (* …and the checkbox… *)
- GetDItem(theDialog, kCheckBox, itemType, itemHandle, itemRect);
- prefs^^.myCheckBox := Boolean(GetCtlValue(ControlHandle(itemHandle)));
-
- (* Finally, copy all the key codes from the temporary storage. *)
- for itemNo := 0 to kLastKey - kFirstKey do
- prefs^^.keyCodes[itemNo] := gTempKeyCodes[itemNo];
-
- returnValue := true; (* OK *)
- end;
- ;
- DisposeDialog(theDialog);
- SetPort(oldPort);
- AskKeys := returnValue;
- end; (*AskKeys*)
-
-
-
- (*InitPrefs*)
- (*This procedure loads the preferences from a resource in the current resource file,*)
- (*creating a new one if there is none.*)
-
- procedure InitPrefs;
-
- var
- i: Integer;
- ignoreErr: OSErr;
-
- begin
- gPrefs := PrefsHnd(Get1Resource('Pref', 0));
- if gPrefs = nil then (*Didn't exist - create it!*)
- begin
- gPrefs := PrefsHnd(NewHandle(sizeof(PrefsRec)));
- if gPrefs = nil then
- ExitToShell; (*Insert error message here*)
-
- (* We should fill it with some values here *)
-
- AddResource(Handle(gPrefs), 'Pref', 0, 'Preferences');
- end
- else (*Did exist - check the size!*)
- if (GetHandleSize(Handle(gPrefs)) < sizeof(PrefsRec)) then
- SetHandleSize(Handle(gPrefs), sizeof(PrefsRec));
- end; (*InitScores*)
-
-
- (* Standard inits *)
-
- procedure InitToolbox;
- begin
- {$ifc UNDEFINED THINK_PASCAL}
- InitGraf(@qd.thePort);
- InitFonts;
- FlushEvents(everyEvent, 0);
- InitWindows;
- InitMenus;
- TEInit;
- InitDialogs(nil);
- {$endc}
- InitCursor;
- end;
-
- (****************** Main program ******************)
-
-
- var
- str: Str255;
- i: Integer;
- gAppFile, gPrefFile: Integer;
-
- begin
- InitToolbox;
-
- (*Get the prefs file - create as necessary.*)
- if SetPrefFile('KeyConfig Preferences', '????', 'pref', gAppFile, gPrefFile) then
- ;
-
- (*Set the current resource file to the preference file before InitScores*)
- if gPrefFile <> 0 then
- UseResFile(gPrefFile);
- InitPrefs;
- UseResFile(gAppFile);
-
- if AskKeys(gPrefs) then
- begin
- ChangedResource(Handle(gPrefs));
- WriteResource(Handle(gPrefs));
- end;
-
- CloseResFile(gPrefFile);
-
- end. (*KeyConfig*)